#include "dot_operations.h"

RgbLevelsSettings rgbLevelsSettings;
ThresholdSettings thresholdSettings;
ContrastSettings contrastSettings;
ExponentSettings expSettings;
LogarithmSettings logSettings;
NaturalLogarithmSettings natLogSettings;
MonotoneSettings monotoneSettings;

bool grayscaleSetup( Task *task )
{
	return true;
}

/*
	Gemaakt door Bas Janssens
	Omgebouw door Gerco Koks
*/
bool grayscale( Image &img, void *data )
{
	Generic gen;
	img = gen.covertToGrayscale( img );

	return true;
}
/*
	Naam: Mark van der Steen
*/
wchar_t strMono1[32];
wchar_t strMono2[32];
wchar_t strMono3[32];
BOOL CALLBACK monotoneSetupProc(	HWND hWndDialog,
									UINT message,
									WPARAM wParam,
									LPARAM lParam )
{
	switch( message )
	{
	case WM_INITDIALOG:

		// de range van de slider instellen
		SendMessage(	GetDlgItem( hWndDialog, IDC_SLIDER_MONO1 ),
			TBM_SETRANGE, true, MAKELONG( 1, 10 ) );

		SendMessage(	GetDlgItem( hWndDialog, IDC_SLIDER_MONO2 ),
			TBM_SETRANGE, true, MAKELONG( 1, 10 ) );

		SendMessage(	GetDlgItem( hWndDialog, IDC_SLIDER_MONO3 ),
			TBM_SETRANGE, true, MAKELONG( 1, 10 ) );

		// positie van de slider
		SendMessage(	GetDlgItem( hWndDialog, IDC_SLIDER_MONO1 ),
			TBM_SETPOS, true, (long)1 );

		SendMessage(	GetDlgItem( hWndDialog, IDC_SLIDER_MONO2 ),
			TBM_SETPOS, true, (long)1 );

		SendMessage(	GetDlgItem( hWndDialog, IDC_SLIDER_MONO3 ),
			TBM_SETPOS, true, (long)1 );

		// default waarde van het invoerveld
		SetDlgItemText(	hWndDialog, IDC_MONO1, L"1" );
		SetDlgItemText(	hWndDialog, IDC_MONO2, L"1" );
		SetDlgItemText(	hWndDialog, IDC_MONO3, L"1" );

		break;
	case WM_COMMAND:
		switch( LOWORD( wParam ) )
		{
		case IDOK:
			if( GetDlgItemText( hWndDialog, IDC_MONO1, strMono1, 32 ) == 0 )
				strMono1[ 0 ] = L'\0';
			
			if( GetDlgItemText( hWndDialog, IDC_MONO2, strMono2, 32 ) == 0 )
				strMono2[ 0 ] = L'\0';

			if( GetDlgItemText( hWndDialog, IDC_MONO3, strMono3, 32 ) == 0 )
				strMono3[ 0 ] = L'\0';
			
			monotoneSettings._mono1 = _wtoi( strMono1 );
			monotoneSettings._mono2 = _wtoi( strMono2 );
			monotoneSettings._mono3 = _wtoi( strMono3 );
			

		case IDCANCEL:
			EndDialog( hWndDialog, wParam );
			return true;
		case IDC_MONO1:
			wchar_t buf[ 5 ];
			if( HIWORD( wParam ) == EN_CHANGE )
			{	
				GetDlgItemText( hWndDialog, IDC_MONO1, buf, 5 );
				SendMessage( GetDlgItem(hWndDialog, IDC_SLIDER_MONO1 ), TBM_SETPOS, TRUE, _wtoi( buf ) );
			}
		case IDC_MONO2:
			if( HIWORD( wParam ) == EN_CHANGE )
			{	
				GetDlgItemText( hWndDialog, IDC_MONO2, buf, 5 );
				SendMessage( GetDlgItem(hWndDialog, IDC_SLIDER_MONO2 ), TBM_SETPOS, TRUE, _wtoi( buf ) );
			}
		case IDC_MONO3:
			if( HIWORD( wParam ) == EN_CHANGE )
			{	
				GetDlgItemText( hWndDialog, IDC_MONO3, buf, 5 );
				SendMessage( GetDlgItem(hWndDialog, IDC_SLIDER_MONO3 ), TBM_SETPOS, TRUE, _wtoi( buf ) );
			}
			break;
		}
		break;
	case WM_HSCROLL:
		if( (HWND) lParam == GetDlgItem( hWndDialog, IDC_SLIDER_MONO1 ) )
		{
			if( LOWORD( wParam ) == SB_THUMBPOSITION || LOWORD( wParam ) == SB_THUMBTRACK )
			{
				wchar_t buf[ 5 ];
				_itow( (short)HIWORD( wParam ), buf, 10 );
				SetDlgItemText( hWndDialog, IDC_MONO1, buf );
			}
		}

		if( (HWND) lParam == GetDlgItem( hWndDialog, IDC_SLIDER_MONO2 ) )
		{
			if( LOWORD( wParam ) == SB_THUMBPOSITION || LOWORD( wParam ) == SB_THUMBTRACK )
			{
				wchar_t buf[ 5 ];
				_itow( (short)HIWORD( wParam ), buf, 10 );
				SetDlgItemText( hWndDialog, IDC_MONO2, buf );
			}
		}

		if( (HWND) lParam == GetDlgItem( hWndDialog, IDC_SLIDER_MONO3 ) )
		{
			if( LOWORD( wParam ) == SB_THUMBPOSITION || LOWORD( wParam ) == SB_THUMBTRACK )
			{
				wchar_t buf[ 5 ];
				_itow( (short)HIWORD( wParam ), buf, 10 );
				SetDlgItemText( hWndDialog, IDC_MONO3, buf );
			}
		}
		break;
	}
	return false;
}

/*
	Naam: Mark van der Steen
*/
bool monotoneSetup( Task *task )
{
	MainWindow *mainWindow = MainWindow::instance();
	if( DialogBox( 
		mainWindow->hInstance(),
		MAKEINTRESOURCE( IDD_DIALOG_MONOTONE ),
		mainWindow->hWnd(),
		(DLGPROC) &monotoneSetupProc ) == IDOK )
	{
		return true;
	}
	return false;
}
/*
	Naam: Mark van der Steen
*/
bool monotone( Image &img, void *data )
{
	double value = 0.0;
	unsigned int row, col, chan;
	// loop door de rijen
	for( row = 0; row < img.height(); row++ )
	{
		// loop door de kolommen
		for( col = 0; col < img.width(); col++ )	   //kolommen
		{
			value = 0.0;
			// loop door de channels
			for( chan = 0; chan < 3; chan++ )
			{
				//voor pixels in channel 0 wordt vermenigvuldigt met 0.11 en toegekent aan value
				if(chan == 0)
					value += (img[ row ][ col ][ chan ] ) * 0.11;
				//voor pixels in channel 1 wordt vermenigvuldigt met 0.59 en opgeteld bij value
				if(chan == 1)
					value += (img[ row ][ col ][ chan ] ) * 0.59;
				//voor pixels in channel 2 wordt vermenigvuldigt met 0.3 en opgeteld aan value
				if(chan == 2)
					value += (img[ row ][ col ][ chan ] ) * 0.3;
			}

			double gray = value;
			double gray1, gray2, gray3;
			
			for (chan = 0; chan < 3; chan++)
			{
				//voor iedere pixels de juiste kleurwaarde toevoegen
				if(chan == 0){
					if(monotoneSettings._mono1 == 10){
						(img[ row ][ col ][ chan ] ) = (byte)gray;
					}
					else
					gray1 = gray* (monotoneSettings._mono1 / 10);
					gray1 = ( gray1 > 255 ) ? 255 : ( gray1 < 0 ) ? 0 : gray1;
					(img[ row ][ col ][ chan ] ) = (byte)gray1;
				}
		
				if(chan == 1){
					if(monotoneSettings._mono2 == 10){
						(img[ row ][ col ][ chan ] ) = (byte)gray;
					}
					else
					gray2 = gray* (double)(monotoneSettings._mono2 / 10);
					gray2 = ( gray2 > 255 ) ? 255 : ( gray2 < 0 ) ? 0 : gray2;
					(img[ row ][ col ][ chan ] ) = (byte)gray2;
				}
				
				if(chan == 2){
					if(monotoneSettings._mono3 == 10){
						(img[ row ][ col ][ chan ] ) = (byte)gray;
					}
					else
					gray3 = gray* (monotoneSettings._mono3 / 10);
					gray3 = ( gray3 > 255 ) ? 255 : ( gray3 < 0 ) ? 0 : gray3;
					(img[ row ][ col ][ chan ] ) = (byte)gray3;
				}	
			}	
		}
	}
	return true;
}

bool yCbCrSetup( Task *task )
{
	return true;
}

/*
	Naam: Mark van der Steen & Gerco Koks
*/
bool yCbCr( Image &img, void *data )
{
	// members
	unsigned int row, col, chan;
	double Y, Cb, Cr, R, G, B;
	double delta = 128;


		// loop door de rijen
		for( row = 0; row < img.height(); row++ )
		{
			// loop door de kolommen
			for( col = 0; col < img.width(); col++ )
			{
				// loop door de channels
				for( chan = 0; chan < 3; chan++ )
				{
					// waardes ophalen
					if( chan == img.BLUE )
						B = (double)img[row][col][chan];
					else if( chan == img.GREEN )
						G = (double)img[row][col][chan];
					else if( chan == img.RED )
						R = (double)img[row][col][chan];
				}
				
				// YCrCb conversie
				Y = (0.299 * R) + (0.587* G) + (0.114 * B);
				Cb = ((Y - B) / 2) + delta;
				Cr = (( Y - R ) / 1.6) + delta;

				// de berekende waardes terugzetten
				for( chan = 0; chan < 3; chan++ )
				{
					if( chan == img.BLUE )
						img[row][col][chan] = (byte)Y;
					else if( chan == img.GREEN )
						img[row][col][chan] = (byte)Cb;
					else if( chan == img.RED )
						img[row][col][chan] = (byte)Cr;
				}
			}
		}
		delete data;
		return true;
}

/*	Gemaakt door Jeroen:
	RGBLevels */

//Informatie van het RGB Levels Dialoogvenster:
wchar_t rLevel[ 32 ];
wchar_t gLevel[ 32 ];
wchar_t bLevel[ 32 ];

BOOL CALLBACK rgbLevelsSetupProc(
	HWND hWndDialog,
	UINT message,
	WPARAM wParam,
    LPARAM lParam
	)
{
	switch( message )
	{
	case WM_INITDIALOG:
		//Initialiseren van het dialoogvenster:
		
		//Roodwaarden initialiseren op 0%
        SetDlgItemText( hWndDialog, IDC_EDIT_R, L"0" );
		
		//Groenwaarden initialiseren op 0%
        SetDlgItemText( hWndDialog, IDC_EDIT_G, L"0" );

		//Blauwwaarden initialiseren op 0%
        SetDlgItemText( hWndDialog, IDC_EDIT_B, L"0" );
        

		break;
	case WM_COMMAND:
		switch( LOWORD( wParam ) )
		{
		case IDOK:
			{
				//Waardes uit de velden lezen en opslaan in RGBLevelsSettings.
				wchar_t szROffset[32], szGOffset[32], szBOffset[32];
				//Geen van de velden mag leeg zijn				
				if( GetDlgItemText( hWndDialog, IDC_EDIT_R, szROffset, 32 ) == 0 || 
					GetDlgItemText( hWndDialog, IDC_EDIT_G, szGOffset, 32 ) == 0 ||
					GetDlgItemText( hWndDialog, IDC_EDIT_B, szBOffset, 32 ) == 0)
				{
					//One or more fields are left empty. Show a warning and do not close the dialog.
					MessageBox( hWndDialog, L"Voer waarden in!", L"Waarschuwing", MB_OK | MB_ICONEXCLAMATION );
					return FALSE;
				}
				//Als er tekst ingevoerd wordt, de waarde automatisch naar het getal 0 omzetten:			
				rgbLevelsSettings._rOffset = _wtoi( szROffset );
				rgbLevelsSettings._gOffset = _wtoi( szGOffset );
				rgbLevelsSettings._bOffset = _wtoi( szBOffset );
			}
		case IDCANCEL:
			EndDialog( hWndDialog, wParam );
			return TRUE;
		}
		break;
	}
	return FALSE;
}


bool rgbLevelsSetup( Task *task )
{
	MainWindow *mainWindow = MainWindow::instance();
	if( DialogBox(
		mainWindow->hInstance(),
		MAKEINTRESOURCE( IDD_DIALOG_RGBLEVELS ),
		mainWindow->hWnd(),
		(DLGPROC) &rgbLevelsSetupProc ) == IDOK )
	{
		//Allocate a structure and copy the settings. This structure is used in
		//the rgbLevels method.
		task->_data = new RgbLevelsSettings( rgbLevelsSettings );
		return true;
	}
	return false; //The user cancelled the operation.
}
 /*
		Naam: Jeroen van Heugten
		datum: 1 december 2008

		Algoritme om RGB levels aan te passen implementeren
		Voor iedere pixel op Channel 1: Waarde = Waarde x Percentage invoer Rood
		Voor iedere pixel op Channel 2: Waarde = Waarde x Percentage invoer Groen
		Voor iedere pixel op Channel 3: Waarde = Waarde x Percentage invoer Blauw

	 */

bool rgbLevels( Image &img, void *data )
{
	int rOffset, gOffset, bOffset;
	
	rOffset = ( (RgbLevelsSettings*) data )->_rOffset;
	gOffset = ( (RgbLevelsSettings*) data )->_gOffset;
	bOffset = ( (RgbLevelsSettings*) data )->_bOffset;

	// members
	unsigned int row, col, chan;

	// loop door de rijen
		for( row = 0; row < img.height(); row++ )
		{
			// loop door de kolommen
			for( col = 0; col < img.width(); col++ )	   //kolommen
			{
				// loop door de channels
				for( chan = 0; chan < 3; chan++ )
				{
					//voor pixels in channel 0 het ingevoerde percentage BLAUW berekenen
					if(chan == 0)
						{
						img[ row ][ col ][ chan ] =	
						(img[ row ][ col ][ chan ] / 100) * bOffset;
						}
					//voor pixels in channel 1 het ingevoerde percentage GROEN berekenen
					if(chan == 1)
						{
						img[ row ][ col ][ chan ] =	
						(img[ row ][ col ][ chan ] / 100) * gOffset;
						}
					//voor pixels in channel 2 het ingevoerde percentage ROOD berekenen
					if(chan == 2)
						{
						img[ row ][ col ][ chan ] =	
						(img[ row ][ col ][ chan ] / 100) * rOffset;
						}
				}
			}
		}

		delete data;

	return true;
}

wchar_t strLow[32];
wchar_t strHigh[32];
int _auto;
BOOL CALLBACK contrastSetupProc(	HWND hWndDialog,
									UINT message,
									WPARAM wParam,
									LPARAM lParam )
{
	switch( message )
	{
	case WM_INITDIALOG:

		// init CONTRAST
		SendMessage(	GetDlgItem( hWndDialog, IDC_SLIDER_LOW ),
			TBM_SETRANGE, true, MAKELONG( 0, 255 ) );

		// positie van de slider
		SendMessage(	GetDlgItem( hWndDialog, IDC_SLIDER_LOW ),
			TBM_SETPOS, true, (long)128 );

		// default waarde van het invoerveld
		SetDlgItemText(	hWndDialog, IDC_EDIT_LOW, L"0" );

		// init Brightness
		SendMessage(	GetDlgItem( hWndDialog, IDC_SLIDER_HIGH ),
			TBM_SETRANGE, true, MAKELONG( 0, 255 ) );

		// positie van de slider
		SendMessage(	GetDlgItem( hWndDialog, IDC_SLIDER_HIGH ),
			TBM_SETPOS, true, (long)128 );

		// default waarde van het invoerveld
		SetDlgItemText(	hWndDialog, IDC_EDIT_HIGH, L"255" );

		break;
	case WM_COMMAND:
		switch( LOWORD( wParam ) )
		{
		case IDOK:
			if( GetDlgItemText( hWndDialog, IDC_EDIT_LOW, strLow, 32 ) == 0 )
				strLow[ 0 ] = L'\0';
			
			if( GetDlgItemText( hWndDialog, IDC_EDIT_HIGH, strHigh, 32 ) == 0 )
				strHigh[ 0 ] = L'\0';
			
			if( IsDlgButtonChecked( hWndDialog, IDC_CHECK_AUTO ) )
				contrastSettings._auto = true;
			else
				contrastSettings._auto = false;
	
			contrastSettings._low = _wtoi( strLow );
			contrastSettings._high = _wtoi( strHigh );
			

		case IDCANCEL:
			EndDialog( hWndDialog, wParam );
			return true;
		case IDC_EDIT_LOW:
			wchar_t buf[ 5 ];
			if( HIWORD( wParam ) == EN_CHANGE )
			{	
				GetDlgItemText( hWndDialog, IDC_EDIT_LOW, buf, 5 );
				SendMessage( GetDlgItem(hWndDialog, IDC_SLIDER_LOW ), TBM_SETPOS, TRUE, _wtoi( buf ) );
			}
		case IDC_EDIT_HIGH:
			if( HIWORD( wParam ) == EN_CHANGE )
			{	
				GetDlgItemText( hWndDialog, IDC_EDIT_HIGH, buf, 5 );
				SendMessage( GetDlgItem(hWndDialog, IDC_SLIDER_HIGH ), TBM_SETPOS, TRUE, _wtoi( buf ) );
			}
			break;
		}
		break;
	case WM_HSCROLL:
		if( (HWND) lParam == GetDlgItem( hWndDialog, IDC_SLIDER_LOW ) )
		{
			if( LOWORD( wParam ) == SB_THUMBPOSITION || LOWORD( wParam ) == SB_THUMBTRACK )
			{
				wchar_t buf[ 5 ];
				_itow( (short)HIWORD( wParam ), buf, 10 );
				SetDlgItemText( hWndDialog, IDC_EDIT_LOW, buf );
			}
		}

		if( (HWND) lParam == GetDlgItem( hWndDialog, IDC_SLIDER_HIGH ) )
		{
			if( LOWORD( wParam ) == SB_THUMBPOSITION || LOWORD( wParam ) == SB_THUMBTRACK )
			{
				wchar_t buf[ 5 ];
				_itow( (short)HIWORD( wParam ), buf, 10 );
				SetDlgItemText( hWndDialog, IDC_EDIT_HIGH, buf );
			}
		}
		break;
	}
	return false;
}

/*
	gemaakt door Gerco Koks

*/
bool contrastSetup( Task *task )
{
	MainWindow *mainWindow = MainWindow::instance();
	if( DialogBox( 
		mainWindow->hInstance(),
		MAKEINTRESOURCE( IDD_DIALOG_CONTRAST ),
		mainWindow->hWnd(),
		(DLGPROC) &contrastSetupProc ) == IDOK )
	{
		return true;
	}
	return false;
	
}

/*
	Gemaakt door gerco Koks
	gebruikte formule P(x,y) = P(x,y) = (Q(x,y) - C)*(b-c)/(d-c)+a
*/
bool contrast( Image &img, void *data )
{
	// voor de loop door de afbeelding
	unsigned int row, col, chan = NULL;
	// member waar de pixel waarde ingestopt wordt
	double pixel, px;
	// vector om de histogram waarden in op te slaan
	std::vector<unsigned int> _histogram;
	unsigned int _lPixLimit = 0;
	unsigned int _hPixLimit = 255;
	unsigned int _devidedLimit;
	unsigned int _lColorValue, _hColorValue = 0;
		
	if( contrastSettings._auto )
	{
		// automatisch contrast toepassen. Hiervoor zal de hoogste en laagste kleurwaarde 
		// wat de afbeelding bevat moeten worden bepaald aan de hand van een histogram.

		_histogram.resize( 256 );
		// alles op 0 initialiseren
		for( int i = 0; i < 256; i++ )
		{
			_histogram[ i ] = 0;
		}
		
		// histogram vullen
		for( row = 0; row < img.height(); row++ )
		{
			for( col = 0; col < img.width(); col++ )
			{
				px = 0.0;
				for( chan = 0; chan < 3; chan++ )
				{
					
					if(chan == 0)
						px += (unsigned int)img[ row ][ col ][ chan ] * 0.11;
					if(chan == 1)
						px += (unsigned int)img[ row ][ col ][ chan ] * 0.59;
					if(chan == 2)
						px += (unsigned int)img[ row ][ col ][ chan ] * 0.3;
				}
				
					// niet groter dan 255 en niet kleiner dan 0;
				px = ( px > 255 ) ? 255 : ( px < 0 ) ? 0 : Math::Round(px);
										
				// de opgehaalde waarde wordt als index gebruik
				// en deze wordt met 1 opgehoogd
				// 3x namelijk voor iedere channel 1
				for( int i = 0; i < 3; i++ )
				{
					_histogram[(int)px] += 1;
				}
			
			}
		}

		int size = _histogram.size();
		// kleinste kleurwaarde bepalen
		for( int i = 0; i < size; i++ )
		{
			if( _histogram[ i ] != 0 )
			{
				( i == 0 ) ? _lColorValue = i : _lColorValue = (i - 1);
				if( _histogram[ i+1 ] != 0|| _histogram[ i+2 ] != 0 || _histogram[ i+3 ] != 0)
					break;
			}
		}
		
		// grootste kleurwaarde bepalen
		for( int i = (size-1); i > 0 ; i-- )
		{
			if( _histogram[ i ] != 0 )
			{
				( i == 255 ) ? _hColorValue = i : _hColorValue = ( i + 1 );
				if( _histogram[ i-1 ] != 0|| _histogram[ i-2 ] != 0 || _histogram[ i-3 ] != 0)
					break;
			}
		}
	}
	else
	{
		_lColorValue = contrastSettings._low;
		_hColorValue = contrastSettings._high;
	}
	
	_devidedLimit = (_hColorValue - _lColorValue) == 0 ? 1 : (_hColorValue - _lColorValue);

	// het algortime
	for( row = 0; row < img.height(); row++ )
	{
		for( col = 0; col < img.width(); col++ )
		{
			for( chan = 0; chan < 3; chan++ )
			{
				pixel = img[row][col][chan];
				pixel = (double)( pixel - _lColorValue ) *
					( ( _hPixLimit - _lPixLimit ) / ( _devidedLimit ) ) + _lPixLimit;

				( pixel > 255 ) ? pixel = 255 : ( pixel < 0 ) ? pixel = 0 : pixel;

				img[row][col][chan] = (byte)pixel;

			}
		}
	}
	return true;
}

bool invertSetup( Task *task )
{
	return true;
}

/*
Jeroen van Heugten, 18-12-2008
Methode voor negatief maken (Invert)
*/

bool invert( Image &img, void *data )
{
	// members
	unsigned int row, col, chan;

		// loop door de rijen
		for( row = 0; row < img.height(); row++ )
		{
			// loop door de kolommen
			for( col = 0; col < img.width(); col++ )	   //kolommen
			{
				// loop door de channels
				for( chan = 0; chan < 3; chan++ )
				{
						//Waarde omkeren					
						img[ row ][ col ][ chan ] =	255 - (img[ row ][ col ][ chan ]);
					
				}
			}
		}
		//opruimen
		delete data;

	return true;
}

/*
	Naam: Mark van der Steen
*/
BOOL CALLBACK thresholdSetupProc(
	HWND hWndDialog,
	UINT message,
	WPARAM wParam,
    LPARAM lParam
	)
{
	switch( message )
	{
	case WM_INITDIALOG:
		
		// range van de slider
		SendMessage( GetDlgItem( hWndDialog, IDC_SLIDER_THRESHOLD ),
			TBM_SETRANGE, true, MAKELONG( 0, 255 ) );

		// default waarde van de edit bx
		SetDlgItemText( hWndDialog, IDC_EDIT_THRESHOLD, L"0" );

		break;
	case WM_COMMAND:
		switch( LOWORD( wParam ) )
		{
		case IDOK:
			{
				//Waardes uit de velden lezen en opslaan in thresholdSettings.
				wchar_t szthreshold[32];
				//Geen van de velden mag leeg zijn				
				if( GetDlgItemText( hWndDialog, IDC_EDIT_THRESHOLD, szthreshold, 32 ) == 0)
				{
					//One or more fields are left empty. Show a warning and do not close the dialog.
					MessageBox( hWndDialog, L"Voer waarden in!", L"Waarschuwing", MB_OK | MB_ICONEXCLAMATION );
					return FALSE;
				}
				//Als er tekst ingevoerd wordt, de waarde automatisch naar het getal 0 omzetten:			
				thresholdSettings._threshold = _wtoi( szthreshold );
				
			}
		case IDCANCEL:
			EndDialog( hWndDialog, wParam );
			return TRUE;
		case IDC_EDIT_THRESHOLD:
			wchar_t buf[5];
			if( HIWORD( wParam ) == EN_CHANGE )
			{
				GetDlgItemText( hWndDialog, IDC_EDIT_THRESHOLD, buf, 5 );
				SendMessage( GetDlgItem( hWndDialog, IDC_SLIDER_THRESHOLD ), TBM_SETPOS, true, _wtoi(buf) );
			}
			break;
		}
		break;
	case WM_HSCROLL:
		if( (HWND)lParam == GetDlgItem( hWndDialog, IDC_SLIDER_THRESHOLD ) )
		{
			if( LOWORD(wParam) == SB_THUMBPOSITION || LOWORD(wParam) == SB_THUMBTRACK )
			{
				wchar_t buf[5];
				_itow( (short)HIWORD(wParam), buf, 10 );
				SetDlgItemText( hWndDialog, IDC_EDIT_THRESHOLD, buf );
			}
		}
		break;
	}
	return FALSE;
}

/*
	Naam: Mark van der Steen
*/
bool thresholdSetup( Task *task )
{
	MainWindow *mainWindow = MainWindow::instance();
	if( DialogBox(
		mainWindow->hInstance(),
		MAKEINTRESOURCE( IDD_DIALOG_THRESHOLD ),
		mainWindow->hWnd(),
		(DLGPROC) &thresholdSetupProc ) == IDOK )
	{
		//Allocate a structure and copy the settings. This structure is used in
		//the rgbLevels method.
		task->_data = new ThresholdSettings( thresholdSettings );
		return true;
	}
	return false; //The user cancelled the operation.	
}
/*
	Naam: Mark van der Steen
*/
bool threshold( Image &img, void *data )
{
	int threshold;	
	// Waarde ophalen van invoerveld
	threshold = ( (ThresholdSettings*) data )->_threshold;	

	// thresholding uitvoeren op een grijswaarde plaatje
	Generic gen;
	gen.covertToGrayscale(img);

	/*
	Hierboven wordt eerst de image naar een grayscale image omgezet. 
	(Dit is door Bas Janssens geprogrammeer)
	*/
	unsigned int row, col, chan;
	// Loop door de rijen
	for( row = 0; row < img.height(); row++ )
	{
		// Loop door de kolommen
		for( col = 0; col < img.width(); col++ )	   
		{
			/*
			In de onderstaande code wordt de grijswaarde van iedere pixel vergeleken met
			de threshold waarde. Wanneer de grijswaarde kleiner is als de threshold dan wordt
			de pixel naar waarde 0 gezet. Als de grijswaarde groter of gelijk aan de threshold
			is dan wordt de pixel naar waarde 255 gezet.
			*/
			for (chan = 0; chan < 3; chan++)
			{
				img[row][col][chan] = ( img[row][col][chan] < threshold ) ? 0 : 255;
			}
		}
	}
	return true;
}

wchar_t strExpBase[32];

BOOL CALLBACK exponentSetupProc (HWND hWndDialog,
									UINT message,
									WPARAM wParam,
									LPARAM lParam )
{
	switch( message )
	{
	case WM_INITDIALOG:
		//exponent
		SendMessage( GetDlgItem( hWndDialog, IDC_SLIDER_EXP_BASE ),
			TBM_SETRANGE, true, MAKELONG(0, 100));
		SetDlgItemText( hWndDialog, IDC_EDIT_EXP_BASE, L"0" );
		
		break;

		case WM_COMMAND:
			switch( LOWORD( wParam ) )
			{
			case IDOK:
				if( GetDlgItemText( hWndDialog, IDC_EDIT_EXP_BASE, strExpBase, 32 ) == 0 )
					strExpBase[ 0 ] = L'\0';
							
				expSettings.base = _wtoi( strExpBase	);

			case IDCANCEL:
				EndDialog( hWndDialog, wParam );
				return true;
			
			case IDC_EDIT_EXP_BASE:
				wchar_t buf[ 5 ];
				if( HIWORD( wParam ) == EN_CHANGE )
				{	
					GetDlgItemText( hWndDialog, IDC_EDIT_EXP_BASE, buf, 5 );
					SendMessage( GetDlgItem(hWndDialog, IDC_SLIDER_EXP_BASE ), TBM_SETPOS, TRUE, _wtoi( buf ) );
				}
			
				break;
			}
			break;
	
			case WM_HSCROLL:

				if( (HWND) lParam == GetDlgItem( hWndDialog, IDC_SLIDER_EXP_BASE ) )
				{
					if( LOWORD( wParam ) == SB_THUMBPOSITION || LOWORD( wParam ) == SB_THUMBTRACK )
					{
						wchar_t buf[ 5 ];
						_itow( (short)HIWORD( wParam ), buf, 10 );
						SetDlgItemText( hWndDialog, IDC_EDIT_EXP_BASE, buf );
					}
				}
				break;
			}
	return false;
}



bool exponentSetup( Task *task )
{
	MainWindow *mainWindow = MainWindow::instance();
	if( DialogBox( 
		mainWindow->hInstance(),
		MAKEINTRESOURCE( IDD_DIALOG_EXPONENT ),
		mainWindow->hWnd(),
		(DLGPROC) &exponentSetupProc ) == IDOK )
	{
		return true;
	}
	return false;
}



/*
	gemaakt door: Jeroen
	gebruikt algoritme: P(x,y) = ( ( b^Q(x,y) )-1 )  / ( b-1 )
*/

bool exponent( Image &img, void *data )
{
	unsigned int row, col, chan;
	double base = expSettings.base;

	// loop door de rijen
	for( row = 0; row < img.height(); row++ )
		// loop door de kolommen
		for( col = 0; col < img.width(); col++ )
			// loop door de channels
			for( chan = 0; chan < 3; chan++ )
			{ 
				// haal de pixel op
				double original = (double)img[row][col][chan] / 255 ;
				double result;
				// het algoritme
				result =	(pow(base,original) -1) / (base-1);
				
				//Terugplaatsen van de nieuwe waarde in dezelfde positie
				img[row][col][chan] = (byte)(result * 255);

			}
	// en klaar is kees
	return true;
}




wchar_t strScale[32];
wchar_t strOffset[32];
BOOL CALLBACK logarithmSetupProc (HWND hWndDialog,
									UINT message,
									WPARAM wParam,
									LPARAM lParam )
{
	switch( message )
	{
	case WM_INITDIALOG:
		//scale
		SendMessage( GetDlgItem( hWndDialog, IDC_SLIDER_LOG_SCALE ),
			TBM_SETRANGE, true, MAKELONG(0, 100));
		SetDlgItemText( hWndDialog, IDC_EDIT_LOG_SCALE, L"0" );
		// offset
		SendMessage( GetDlgItem( hWndDialog, IDC_SLIDER_LOG_OFFSET ),
			TBM_SETRANGE, true, MAKELONG(-200, 0));
		SetDlgItemText( hWndDialog, IDC_EDIT_LOG_OFFSET, L"-200" );
		break;

		case WM_COMMAND:
			switch( LOWORD( wParam ) )
			{
			case IDOK:
				if( GetDlgItemText( hWndDialog, IDC_EDIT_LOG_SCALE, strScale, 32 ) == 0 )
					strScale[ 0 ] = L'\0';
				if( GetDlgItemText( hWndDialog, IDC_EDIT_LOG_OFFSET, strOffset, 32 ) == 0 )
					strOffset[ 0 ] = L'\0';

				// + 40 omdat 40 de minimale waarde is voor een beetje resultaat
				logSettings.scale = _wtoi( strScale ) + 40;
				logSettings.offset = _wtoi( strOffset );
			case IDCANCEL:
				EndDialog( hWndDialog, wParam );
				return true;
			case IDC_EDIT_LOG_SCALE:
				wchar_t buf[ 5 ];
				if( HIWORD( wParam ) == EN_CHANGE )
				{	
					GetDlgItemText( hWndDialog, IDC_EDIT_LOG_SCALE, buf, 5 );
					SendMessage( GetDlgItem(hWndDialog, IDC_SLIDER_LOG_SCALE ), TBM_SETPOS, TRUE, _wtoi( buf ) );
				}
			case IDC_EDIT_LOG_OFFSET:
				//buf[ 5 ];
				if( HIWORD( wParam ) == EN_CHANGE )
				{	
					GetDlgItemText( hWndDialog, IDC_EDIT_LOG_OFFSET, buf, 5 );
					SendMessage( GetDlgItem(hWndDialog, IDC_SLIDER_LOG_OFFSET ), TBM_SETPOS, TRUE, _wtoi( buf ) );
				}
				break;
			}
			break;
	
			case WM_HSCROLL:

				if( (HWND) lParam == GetDlgItem( hWndDialog, IDC_SLIDER_LOG_SCALE ) )
				{
					if( LOWORD( wParam ) == SB_THUMBPOSITION || LOWORD( wParam ) == SB_THUMBTRACK )
					{
						wchar_t buf[ 5 ];
						_itow( (short)HIWORD( wParam ), buf, 10 );
						SetDlgItemText( hWndDialog, IDC_EDIT_LOG_SCALE, buf );
					}
				}

				if( (HWND) lParam == GetDlgItem( hWndDialog, IDC_SLIDER_LOG_OFFSET ) )
				{
					if( LOWORD( wParam ) == SB_THUMBPOSITION || LOWORD( wParam ) == SB_THUMBTRACK )
					{
						wchar_t buf[ 5 ];
						_itow( (short)HIWORD( wParam ), buf, 10 );
						SetDlgItemText( hWndDialog, IDC_EDIT_LOG_OFFSET, buf );
					}
				}
				break;
			}
	return false;
}




bool logarithmSetup( Task *task )
{
	MainWindow *mainWindow = MainWindow::instance();
	if( DialogBox( 
		mainWindow->hInstance(),
		MAKEINTRESOURCE( IDD_DIALOG_LOG ),
		mainWindow->hWnd(),
		(DLGPROC) &logarithmSetupProc ) == IDOK )
	{
		return true;
	}
	return false;
}

/*
	gemaakt door: Jeroen van Heugten
	gebruikt algoritme: P(x,y) = scale * log( q(x,y)+1 ) + offset;
*/
bool logarithm( Image &img, void *data )
{
	unsigned int row, col, chan;
	double scale = logSettings.scale;
	double offset = logSettings.offset;

	// loop door de rijen
	for( row = 0; row < img.height(); row++ )
		// loop door de kolommen
		for( col = 0; col < img.width(); col++ )
			// loop door de channels
			for( chan = 0; chan < 3; chan++ )
			{ 
				// haal de pixel op
				double result = (double)img[row][col][chan];
				// het algoritme
				result = scale * log10( result + 1 ) + offset;
				// niet groter dan 255 en kleiner dan 0
				result = (result > 255) ? 255 : ( result < 0 ) ? 0 : result;
				// sla de pixel op
				img[row][col][chan] = (byte)result;
			}
	// en klaar is kees
	return true;
}




wchar_t strNatScale[32];
wchar_t strNatOffset[32];
BOOL CALLBACK naturalLogarithmSetupProc (HWND hWndDialog,
									UINT message,
									WPARAM wParam,
									LPARAM lParam )
{
	switch( message )
	{
	case WM_INITDIALOG:
		//scale
		SendMessage( GetDlgItem( hWndDialog, IDC_SLIDER_NAT_SCALE ),
			TBM_SETRANGE, true, MAKELONG(0, 100));
		SetDlgItemText( hWndDialog, IDC_EDIT_NAT_SCALE, L"0" );
		// offset
		SendMessage( GetDlgItem( hWndDialog, IDC_SLIDER_NAT_OFFSET ),
			TBM_SETRANGE, true, MAKELONG(-200, 0));
		SetDlgItemText( hWndDialog, IDC_EDIT_NAT_OFFSET, L"-200" );
		break;

		case WM_COMMAND:
			switch( LOWORD( wParam ) )
			{
			case IDOK:
				if( GetDlgItemText( hWndDialog, IDC_EDIT_NAT_SCALE, strNatScale, 32 ) == 0 )
					strScale[ 0 ] = L'\0';
				if( GetDlgItemText( hWndDialog, IDC_EDIT_NAT_OFFSET, strNatOffset, 32 ) == 0 )
					strOffset[ 0 ] = L'\0';

				// + 40 omdat 40 de minimale waarde is voor een beetje resultaat
				natLogSettings.scale = _wtoi( strNatScale ) + 40 ;
				natLogSettings.offset = _wtoi( strNatOffset );
			case IDCANCEL:
				EndDialog( hWndDialog, wParam );
				return true;
			case IDC_EDIT_LOG_SCALE:
				wchar_t buf[ 5 ];
				if( HIWORD( wParam ) == EN_CHANGE )
				{	
					GetDlgItemText( hWndDialog, IDC_EDIT_NAT_SCALE, buf, 5 );
					SendMessage( GetDlgItem(hWndDialog, IDC_SLIDER_NAT_SCALE ), TBM_SETPOS, TRUE, _wtoi( buf ) );
				}
			case IDC_EDIT_NAT_OFFSET:
				//buf[ 5 ];
				if( HIWORD( wParam ) == EN_CHANGE )
				{	
					GetDlgItemText( hWndDialog, IDC_EDIT_NAT_OFFSET, buf, 5 );
					SendMessage( GetDlgItem(hWndDialog, IDC_SLIDER_NAT_OFFSET ), TBM_SETPOS, TRUE, _wtoi( buf ) );
				}
				break;
			}
			break;
	
			case WM_HSCROLL:

				if( (HWND) lParam == GetDlgItem( hWndDialog, IDC_SLIDER_NAT_SCALE ) )
				{
					if( LOWORD( wParam ) == SB_THUMBPOSITION || LOWORD( wParam ) == SB_THUMBTRACK )
					{
						wchar_t buf[ 5 ];
						_itow( (short)HIWORD( wParam ), buf, 10 );
						SetDlgItemText( hWndDialog, IDC_EDIT_NAT_SCALE, buf );
					}
				}

				if( (HWND) lParam == GetDlgItem( hWndDialog, IDC_SLIDER_NAT_OFFSET ) )
				{
					if( LOWORD( wParam ) == SB_THUMBPOSITION || LOWORD( wParam ) == SB_THUMBTRACK )
					{
						wchar_t buf[ 5 ];
						_itow( (short)HIWORD( wParam ), buf, 10 );
						SetDlgItemText( hWndDialog, IDC_EDIT_NAT_OFFSET, buf );
					}
				}
				break;
			}
	return false;
}




bool naturalLogarithmSetup( Task *task )
{
	MainWindow *mainWindow = MainWindow::instance();
	if( DialogBox( 
		mainWindow->hInstance(),
		MAKEINTRESOURCE( IDD_DIALOG_NAT ),
		mainWindow->hWnd(),
		(DLGPROC) &naturalLogarithmSetupProc ) == IDOK )
	{
		return true;
	}
	return false;
}


/*
	gemaakt door: Gerco Koks
	gebruikt algoritme: P(x,y) = scale * log( q(x,y)+1 ) + offset;
*/
bool naturalLogarithm( Image &img, void *data )
{
	unsigned int row, col, chan;
	double scale = natLogSettings.scale;
	double offset = natLogSettings.offset;

	// loop door de rijen
	for( row = 0; row < img.height(); row++ )
		// loop door de kolommen
		for( col = 0; col < img.width(); col++ )
			// loop door de channels
			for( chan = 0; chan < 3; chan++ )
			{ 
				// haal de pixel op
				double result = (double)img[row][col][chan];
				// het algoritme
				result = scale * log( result + 1 ) + offset;
				// niet groter dan 255 en kleiner dan 0
				result = (result > 255) ? 255 : ( result < 0 ) ? 0 : result;
				// sla de pixel op
				img[row][col][chan] = (byte)result;
			}
	// en klaar is kees
	return true;
}